from functools import wraps
from flask import jsonify, request
from flask_jwt_extended import get_jwt_identity
from app.models.user import User
from app.models.work_order import WorkOrder
from app.models import db
from datetime import datetime
import traceback

def get_current_user():
    """获取当前登录用户"""
    current_user_id = get_jwt_identity()
    return User.query.get(current_user_id)

def require_role(*allowed_roles):
    """权限检查装饰器"""
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            current_user = get_current_user()
            if not current_user or current_user.role not in allowed_roles:
                return jsonify({'error': '权限不足'}), 403
            return f(*args, **kwargs)
        return decorated_function
    return decorator

def handle_db_error(operation_name="操作"):
    """数据库错误处理装饰器"""
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            try:
                return f(*args, **kwargs)
            except Exception as e:
                db.session.rollback()
                error_message = str(e) + "\n" + traceback.format_exc()
                print(f"Error in {operation_name}: {error_message}")
                return jsonify({'error': str(e)}), 500
        return decorated_function
    return decorator

def parse_datetime(date_str):
    """解析日期时间字符串"""
    if not date_str:
        return None
    
    formats = [
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%d %H:%M',
        '%Y-%m-%d',
        '%Y-%m-%dT%H:%M:%S',
        '%Y-%m-%dT%H:%M:%S.%f',
        '%Y-%m-%dT%H:%M:%SZ',
        '%Y-%m-%dT%H:%M:%S.%fZ'
    ]
    
    for fmt in formats:
        try:
            return datetime.strptime(date_str, fmt)
        except ValueError:
            continue
    
    raise ValueError(f"无法解析日期时间格式: {date_str}")

def apply_user_filter(query, current_user, area_filter=True, status=None):
    """根据用户角色应用数据过滤
    
    Args:
        query: 工单查询对象
        current_user: 当前用户
        area_filter: 是否启用区域过滤，默认为True
        status: 工单状态，用于特定状态的过滤逻辑，支持逗号分隔的多状态
    """
    # 处理多状态参数
    status_list = []
    if status:
        if ',' in status:
            status_list = [s.strip() for s in status.split(',')]
        else:
            status_list = [status]
    
    # 管理员可以看到所有工单，不需要过滤
    if current_user.role == 'admin':
        return query
        
    # 普通用户的过滤逻辑
    if current_user.role == 'user':
        # 如果是待接单状态且启用区域过滤
        if 'pending' in status_list and area_filter:
            # 查询用户所属的区域
            user_areas = []
            if current_user.area_id:
                user_areas.append(current_user.area_id)
            
            # 获取用户关联的所有区域
            from app.models.user_area import UserArea
            user_area_relations = UserArea.query.filter_by(user_id=current_user.id).all()
            for relation in user_area_relations:
                if relation.area_id not in user_areas:
                    user_areas.append(relation.area_id)
            
            # 待接单工单：显示用户区域所属的无负责人工单
            if user_areas:
                query = query.filter(
                    db.and_(
                        WorkOrder.area_id.in_(user_areas),
                        db.or_(
                            WorkOrder.assignee_id.is_(None),
                            WorkOrder.assignee_id == ''
                        )
                    )
                )
            else:
                # 如果用户没有关联区域，则不显示任何待接单工单
                query = query.filter(WorkOrder.id < 0)  # 不会匹配任何记录
        
        # 如果是待接单状态但禁用区域过滤
        elif 'pending' in status_list and not area_filter:
            # 显示所有无负责人的待接单工单
            query = query.filter(
                db.or_(
                    WorkOrder.assignee_id.is_(None),
                    WorkOrder.assignee_id == ''
                )
            )
        
        # 处理中和已完成工单：仅显示负责人是用户的工单
        elif any(s in status_list for s in ['in_progress', 'completed', 'cancelled']):
            query = query.filter(WorkOrder.assignee_id == current_user.id)
        
        # 其他情况（没有指定status或其他状态）：显示用户创建的、分配给用户的工单，以及用户区域内的待接单工单
        else:
            if area_filter:
                # 查询用户所属的区域
                user_areas = []
                if current_user.area_id:
                    user_areas.append(current_user.area_id)
                
                # 获取用户关联的所有区域
                from app.models.user_area import UserArea
                user_area_relations = UserArea.query.filter_by(user_id=current_user.id).all()
                for relation in user_area_relations:
                    if relation.area_id not in user_areas:
                        user_areas.append(relation.area_id)
                
                # 显示：1) 用户创建的工单 2) 分配给用户的工单 3) 用户区域内的待接单工单
                conditions = [
                    WorkOrder.creator_id == current_user.id,
                    WorkOrder.assignee_id == current_user.id
                ]
                
                # 添加用户区域内的待接单工单
                if user_areas:
                    conditions.append(
                        db.and_(
                            WorkOrder.area_id.in_(user_areas),
                            WorkOrder.status == 'pending',
                            db.or_(
                                WorkOrder.assignee_id.is_(None),
                                WorkOrder.assignee_id == ''
                            )
                        )
                    )
                
                query = query.filter(db.or_(*conditions))
            else:
                # 禁用区域过滤时：显示用户创建的、分配给用户的工单，以及所有待接单工单
                query = query.filter(
                    db.or_(
                        WorkOrder.creator_id == current_user.id,
                        WorkOrder.assignee_id == current_user.id,
                        db.and_(
                            WorkOrder.status == 'pending',
                            db.or_(
                                WorkOrder.assignee_id.is_(None),
                                WorkOrder.assignee_id == ''
                            )
                        )
                    )
                )
    
    # 维护人员角色的过滤逻辑
    elif current_user.role == 'worker':
        # 如果启用区域过滤
        if area_filter:
            # 查询维护人员所属的区域
            worker_areas = []
            if current_user.area_id:
                worker_areas.append(current_user.area_id)
            
            # 获取维护人员关联的所有区域
            from app.models.user_area import UserArea
            worker_area_relations = UserArea.query.filter_by(user_id=current_user.id).all()
            for relation in worker_area_relations:
                if relation.area_id not in worker_areas:
                    worker_areas.append(relation.area_id)
            
            # 显示：1) 用户创建的工单 2) 分配给用户的工单 3) 用户区域内的工单
            conditions = [
                WorkOrder.creator_id == current_user.id,
                WorkOrder.assignee_id == current_user.id
            ]
            
            # 添加用户区域内的工单
            if worker_areas:
                conditions.append(WorkOrder.area_id.in_(worker_areas))
            
            query = query.filter(db.or_(*conditions))
        else:
            # 禁用区域过滤时：显示用户创建的、分配给用户的工单，以及所有工单
            query = query.filter(
                db.or_(
                    WorkOrder.creator_id == current_user.id,
                    WorkOrder.assignee_id == current_user.id
                )
            )
    
    # 经理角色的过滤逻辑
    elif current_user.role == 'manager':
        # 如果启用区域过滤
        if area_filter:
            # 查询经理所属的区域
            manager_areas = []
            if current_user.area_id:
                manager_areas.append(current_user.area_id)
            
            # 获取经理关联的所有区域
            from app.models.user_area import UserArea
            manager_area_relations = UserArea.query.filter_by(user_id=current_user.id).all()
            for relation in manager_area_relations:
                if relation.area_id not in manager_areas:
                    manager_areas.append(relation.area_id)
            
            # 如果是待接单状态
            if 'pending' in status_list:
                # 待接单工单：显示经理区域所属的无负责人工单
                if manager_areas:
                    query = query.filter(
                        db.and_(
                            WorkOrder.area_id.in_(manager_areas),
                            db.or_(
                                WorkOrder.assignee_id.is_(None),
                                WorkOrder.assignee_id == ''
                            )
                        )
                    )
                else:
                    # 如果经理没有关联区域，则不显示任何待接单工单
                    query = query.filter(WorkOrder.id < 0)  # 不会匹配任何记录
            
            # 处理中和已完成工单：显示经理区域内所有的工单
            elif any(s in status_list for s in ['in_progress', 'completed', 'cancelled']):
                if manager_areas:
                    query = query.filter(WorkOrder.area_id.in_(manager_areas))
                else:
                    # 如果经理没有关联区域，则不显示任何工单
                    query = query.filter(WorkOrder.id < 0)  # 不会匹配任何记录
            
            # 其他情况：按区域过滤
            elif manager_areas:
                query = query.filter(WorkOrder.area_id.in_(manager_areas))
        
        # 如果不启用区域过滤，则按组过滤
        elif current_user.group_id:
            query = query.filter(WorkOrder.group_id == current_user.group_id)
    
    return query

def validate_work_order_permission(work_order, current_user, operation="view"):
    """验证工单操作权限"""
    
    if current_user.role == 'admin':
        return True
    
    if current_user.role == 'manager':
        # 检查组权限
        if current_user.group_id and work_order.group_id == current_user.group_id:
            return True
        
        # 检查区域权限：经理可以查看和管理自己区域内的工单
        if work_order.area_id:
            # 检查经理的主区域
            if current_user.area_id == work_order.area_id:
                return True
            
            # 检查经理的多区域关联
            from app.models.user_area import UserArea
            manager_area_relations = UserArea.query.filter_by(
                user_id=current_user.id, 
                area_id=work_order.area_id
            ).first()
            if manager_area_relations:
                return True
    
    # worker 角色权限处理
    if current_user.role == 'worker':
        # 查看权限：创建者、被分配者，或同区域工单
        if operation == "view":
            # 如果是创建者或被分配者，直接允许（不受区域限制）
            if (work_order.creator_id == current_user.id or 
                work_order.assignee_id == current_user.id):
                return True
            
            # 检查区域权限：维护人员可以查看自己区域内的工单
            if work_order.area_id:
                # 检查用户的主区域
                if current_user.area_id == work_order.area_id:
                    return True
                
                # 检查用户的多区域关联
                from app.models.user_area import UserArea
                user_area_relations = UserArea.query.filter_by(
                    user_id=current_user.id, 
                    area_id=work_order.area_id
                ).first()
                if user_area_relations:
                    return True
            
            # 如果工单没有区域限制，且用户有权限查看，则允许
            # 这里可以根据业务需求调整，目前设为不允许查看无区域工单
            return False
        
        # 更新权限：创建者、被分配者，或接单操作
        if operation == "update":
            # 允许接单操作：将未分配的工单分配给自己
            from flask import request
            data = request.get_json() if request else {}
            
            if (data.get('assignee_id') == current_user.id and 
                (work_order.assignee_id is None or work_order.assignee_id == '')):
                # 接单操作还需要检查区域权限
                if work_order.area_id:
                    # 检查用户的主区域
                    if current_user.area_id == work_order.area_id:
                        return True
                    
                    # 检查用户的多区域关联
                    from app.models.user_area import UserArea
                    user_area_relations = UserArea.query.filter_by(
                        user_id=current_user.id, 
                        area_id=work_order.area_id
                    ).first()
                    if user_area_relations:
                        return True
                    
                    # 如果不在用户区域内，拒绝接单
                    return False
                else:
                    # 如果工单没有区域限制，允许接单
                    return True
            
            return (work_order.creator_id == current_user.id or 
                   work_order.assignee_id == current_user.id)
        
        # 删除权限：仅创建者
        if operation == "delete":
            return work_order.creator_id == current_user.id
    
    if current_user.role == 'user':
        # 查看权限：创建者、被分配者，或同区域工单
        if operation == "view":
            # 如果是创建者或被分配者，直接允许（不受区域限制）
            if (work_order.creator_id == current_user.id or 
                work_order.assignee_id == current_user.id):
                return True
            
            # 检查区域权限：用户可以查看自己区域内的工单
            if work_order.area_id:
                # 检查用户的主区域
                if current_user.area_id == work_order.area_id:
                    return True
                
                # 检查用户的多区域关联
                from app.models.user_area import UserArea
                user_area_relations = UserArea.query.filter_by(
                    user_id=current_user.id, 
                    area_id=work_order.area_id
                ).first()
                if user_area_relations:
                    return True
            
            # 如果工单没有区域限制，且用户有权限查看，则允许
            # 这里可以根据业务需求调整，目前设为不允许查看无区域工单
            return False
        
        # 更新权限：创建者、被分配者，或接单操作
        if operation == "update":
            # 允许接单操作：将未分配的工单分配给自己
            data = request.get_json() if request else {}
            
            if (data.get('assignee_id') == current_user.id and 
                (work_order.assignee_id is None or work_order.assignee_id == '')):
                # 接单操作还需要检查区域权限
                if work_order.area_id:
                    # 检查用户的主区域
                    if current_user.area_id == work_order.area_id:
                        return True
                    
                    # 检查用户的多区域关联
                    from app.models.user_area import UserArea
                    user_area_relations = UserArea.query.filter_by(
                        user_id=current_user.id, 
                        area_id=work_order.area_id
                    ).first()
                    if user_area_relations:
                        return True
                    
                    # 如果不在用户区域内，拒绝接单
                    return False
                else:
                    # 如果工单没有区域限制，允许接单
                    return True
            
            return (work_order.creator_id == current_user.id or 
                   work_order.assignee_id == current_user.id)
        
        # 删除权限：仅创建者
        if operation == "delete":
            return work_order.creator_id == current_user.id
    
    return False